package com.mugui.base.client.net.baghandle;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.mugui.base.base.Autowired;
import com.mugui.base.client.net.bagsend.WsHandle;
import com.mugui.base.client.net.bean.NetBag;
import com.mugui.base.client.net.classutil.DataSave;
import lombok.Getter;
import org.glassfish.tyrus.client.ClientManager;
import org.glassfish.tyrus.client.ClientProperties;

import javax.websocket.*;
import java.io.IOException;
import java.net.URI;

@ClientEndpoint
public class EnhancedWebSocketClient {
    private Session session;
    private String serverUri;
    private int maxRetries;

    private NetHandle handle;

    private WsHandle wsHandle;


    @Getter
    private long init_time = System.currentTimeMillis();


    public EnhancedWebSocketClient(String serverUrl, int maxRetries) {
        handle = DataSave.context.getBean(NetHandle.class);
        wsHandle = DataSave.context.getBean(WsHandle.class);
        pongTask = DataSave.context.getBean(PongTask.class);
        this.serverUri = serverUrl;
        this.maxRetries = maxRetries;
        initializeConnection();
    }

    private void initializeConnection() {
        // 创建Tyrus客户端管理器
        ClientManager clientManager = ClientManager.createClient();
        String proxyHost = System.getProperty("proxyHost");
        String proxyPort = System.getProperty("proxyPort");
        if (StrUtil.isNotBlank(proxyHost)) {
            // 配置代理参数
            clientManager.getProperties().put(ClientProperties.PROXY_URI, "http://" + proxyHost + ":" + proxyPort);
            clientManager.getProperties().put(ClientProperties.INCOMING_BUFFER_SIZE, 1024 * 1024 * 10);
            clientManager.getProperties().put(ClientProperties.REDIRECT_ENABLED, true);

        }

        int retryCount = 0;
        while (retryCount < maxRetries) {
            try {
                clientManager.connectToServer(this, URI.create(serverUri));
                init_time = System.currentTimeMillis();
                return;
            } catch (Exception e) {
                e.printStackTrace();
                retryCount++;
                System.err.println("连接失败，尝试重连 (" + retryCount + "/" + maxRetries + ")" + " " + serverUri);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {
                }
            }
        }
        throw new RuntimeException("无法建立WebSocket连接");
    }

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        System.out.println(session.getId() + "成功连接到服务器" + serverUri);
    }

    @OnMessage
    public void onMessage(String message) {
        if (message.endsWith("pong")) {
            //消息pong 消息
            pongTask.remove(message.split("[|]")[0]);
            return;
        }
        ThreadUtil.execute(new Runnable() {
            @Override
            public void run() {
                handle.WsHandle(NetBag.newBean(NetBag.class, message));
            }
        });
    }

    public boolean sendMessage(WsHandle.SendQueue sendQueue, String message) {
        return sendMessage(sendQueue, message, 0);
    }

    private boolean sendMessage(WsHandle.SendQueue sendQueue, String message, int rei) {
        if (rei > 2) {
            System.err.println("重试次数超限：" + message);
            return false;
        }
        if (session != null && session.isOpen()) {
            synchronized (session) {
                if (session.isOpen()) {
                    try {
                        System.out.println(session.getId() + " 发送消息");
                        session.getBasicRemote().sendText(message);
                        sendQueue.add(EnhancedWebSocketClient.this);
                        return true;
                    } catch (IOException e) {
                        e.printStackTrace();
                        System.err.println(session.getId() + " 消息发送失败，重试" + rei);
                        return sendMessage(sendQueue, message, rei + 1);
                    }
                }
            }
        } else {
            System.err.println(session.getId() + "消息发送失败：连接不可用");
            EnhancedWebSocketClient.this.initializeConnection();
            return sendMessage(sendQueue, message, rei + 1);
        }
        return false;
    }

    private PongTask pongTask;

    public void sendPongMessage(WsHandle.SendQueue sendQueue, String id, String data) {
        boolean b = sendMessage(sendQueue, data);
        if (b) {
            PongTask.PongMsgBean pongMsgBean = new PongTask.PongMsgBean().setId(id).setData(data).setEnhancedWebSocketClient(this).setSendQueue(sendQueue);
            pongTask.add(pongMsgBean);
        }
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        System.err.println(session.getId() + " 连接关闭: " + closeReason.getReasonPhrase());
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println(session.getId() + "发生错误: " + throwable.getMessage());
        throwable.printStackTrace();
        close();
    }

    public void close() {
        try {
            System.out.println("关闭连接: " + this);
            if (session != null) {
                session.close();
                session = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public boolean isOpen() {
        return session != null && session.isOpen();
    }

    @Getter
    private long expire_time = -1;

    public void expire() {
        expire_time = System.currentTimeMillis() + 10 * 60 * 1000;
    }


}